from flask import Flask, jsonify, request
from algorithm.ParallelCompress import ParallelCompress
from algorithm.ParallelMeasure import ParallelMeasure
from algorithm.TraCluster import SNN_DPC
from util.result import ResponseResult
from util.HttpCode import HttpState
import numpy as np
import json
import time

app = Flask(__name__)


@app.route("/compress", methods=["POST"])
def traCompress():
    # 获得请求json对象
    data = request.get_json()
    try:
        # 创建压缩算法并行对象
        parallelCompress = ParallelCompress(
            data["trajectories"], data["algorithmObject"]
        )
        # 执行压缩
        compressed_trajectories = parallelCompress.run()
    except Exception as e:
        result = ResponseResult(
            f"Execution Failed!Caught an exception: {e}",
            HttpState.INTERNAL_SERVER_ERROR.value,
        )
        return jsonify(result.toDict())
    # 包装结果
    result = ResponseResult(
        "Execution Succeeded!",
        HttpState.OK.value,
        {"compressed_trajectories": compressed_trajectories},
    )
    return jsonify(result.toDict())


@app.route("/cluster", methods=["POST"])
def traCluster():
    data = request.get_json()  # 获得请求json对象
    params = data["algorithmObject"]["params"]  # 获取算法对象
    distanceMatrix = None  # 距离矩阵
    try:
        # 如果前端传递距离矩阵，则不需要再计算
        if "distanceMatrix" in data and data["distanceMatrix"] is not None:
            distanceMatrix = np.array(data["distanceMatrix"])
            print("执行缓存！！！")
        else:
            # 创建算法并行对象,并行计算轨迹间相似性
            parallelMeasure = ParallelMeasure(
                data["trajectories"],
                "directionThreshold" in params,
                (
                    params["directionThreshold"]
                    if "directionThreshold" in params
                    else None
                ),
            )
            # 执行距离度量
            spatialMatrix, directionMatrix = parallelMeasure.run()
            # 组合距离度量
            distanceMatrix = (
                (1 - params["directionWeight"]*0.01) * spatialMatrix
                + params["directionWeight"]*0.01 * directionMatrix
                if directionMatrix is not None
                else spatialMatrix
            )
        # 创建snndpc聚类对象
        snn_dpc = SNN_DPC(
            k=params["SNNDPC_PLUS_neighborNum"],
            dis_matrix=distanceMatrix,
            center_num=(
                params["SNNDPC_PLUS_clusterNum"]
                if "SNNDPC_PLUS_clusterNum" in params
                else None
            ),
            discret_ratio=(
                params["SNNDPC_PLUS_outlierRatio"]
                if "SNNDPC_PLUS_outlierRatio" in params
                else None
            ),
        )
        # 获得聚类中心以及样本标签
        indexCentroid, indexAssignment = snn_dpc.run()
    except Exception as e:
        result = ResponseResult(
            f"Execution Failed!Caught an exception: {e}",
            HttpState.INTERNAL_SERVER_ERROR.value,
        )
        return jsonify(result.toDict())
    # 包装结果
    result = ResponseResult(
        "Execution Succeeded!",
        HttpState.OK.value,
        {
            # "spatialMatrix": spatialMatrix.tolist(),
            # "directionMatrix": (
            #     None if directionMatrix is None else directionMatrix.tolist()
            # ),
            "distanceMatrix": distanceMatrix.tolist(),
            "indexCentroid": indexCentroid.tolist(),
            "indexAssignment": indexAssignment.tolist(),
        },
    )
    return jsonify(result.toDict())


if __name__ == "__main__":
    app.run(host="0.0.0.0", port=5001, debug=True)
